package com.kasax.httpsupport;

import android.text.TextUtils;

import com.kasax.httpsupport.utils.Util;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class FormBody extends RequestBody {

    // 限制参数不要过多(ArrayMap效率，而且很少需要破k的参数)
    public static final int MAX_FROM = 1000;

    final Map<String, String> map;

    public FormBody(Builder builder) {
        this.map = builder.map;
    }


    @Override
    String contentType() {
        return Const.CONTENT_TYPE_FORM_BODY;
    }

    @Override
    void writeTo(OutputStream os) throws IOException {
        try {
            os.write(transToString(map).getBytes());
            os.flush();
        } finally {
            if (os != null) {
                os.close();
            }
        }
    }

    /**
     * 拼接请求参数
     *
     * @param map
     * @return
     */
    private String transToString(Map<String, String> map) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            if (!TextUtils.isEmpty(sb)) {
                sb.append("&");
            }
            sb.append(URLEncoder.encode(key, Const.UTF8));
            sb.append("=");
            sb.append(URLEncoder.encode(map.get(key), Const.UTF8));
        }
        return sb.toString();
    }

    public static class Builder {
        private Map<String, String> map;

        public Builder() {
            map = new HashMap<>();
        }

        public Builder add(String key, String value) {
            if (map.size() > MAX_FROM) throw new IndexOutOfBoundsException(" 请求参数过多");
            Util.checkMap(key, value);
            map.put(key, value);
            return this;
        }

        public Builder map(Map<String, String> map) {
            if (map.size() > MAX_FROM) throw new IndexOutOfBoundsException(" 请求参数过多");
            this.map = map;
            return this;
        }

        public FormBody build() {
            return new FormBody(this);
        }

    }
}
